{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f3e24f2e",
   "metadata": {},
   "source": [
    "# 随机基准测试\n",
    "\n",
    "\n",
    "*版权所有 (c) 2021 百度量子计算研究所，保留所有权利。*\n",
    "\n",
    "\n",
    "## 内容概要\n",
    "\n",
    "**注意：运行本教程程序所花费的时间及 Quntum Hub 点数会根据用户所输入的参数不同而不同。用户通常需要花费约半个小时及 100 个点数来获得相对可靠的结果。想要获取更多点数，请通过 [Quantum Hub](https://quantum-hub.baidu.com) 联系我们。首先，登录 [Quantum Hub](https://quantum-hub.baidu.com)，然后进入“意见反馈”页面，点击“获取点数”，然后输入必要的信息。提交您的反馈并等待回复。**\n",
    "\n",
    "在实验中，通常有两种方法来描述超导量子计算机的表现：量子过程层析（Quantum Process Tomography, QPT）和随机基准测试（Randomized Benchmarking, RB）\\[1\\]。量子过程层析可以完整地表征一个量子门的特征，但通过量子过程层析来表征并优化量子门是极度复杂和消耗资源的。而且，量子态制备和测量（State Preparation And Measurement, SPAM）的错误也会影响过程层析。而随机基准测试是一个使用随机化方法对量子门进行基准测试的方法，它可扩展且对制备测量错误不敏感，通过单个参数便能够对门集合进行基准测试。因此，特别是当量子比特的数量增加时，使用随机基准测试对量子硬件进行错误表征是十分高效的。\n",
    "\n",
    "本教程将演示如何使用量脉对自定义噪声模拟器中的某一个量子比特进行随机基准测试，表征特定门操作的平均错误率。教程大纲如下：\n",
    "\n",
    "- 简介\n",
    "- 准备工作\n",
    "- 定义含噪模拟器\n",
    "- 实施随机基准测试\n",
    "- 总结"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05d1e777",
   "metadata": {},
   "source": [
    "## 简介\n",
    "\n",
    "\n",
    "**基本随机基准测试**\n",
    "\n",
    "我们通常随机选取 $m$ 个 Clifford 门依次作用到量子比特上，并添加第 $m+1$ 个门使得整个序列在理想情况下等效于一个单位矩阵酉变换：\n",
    "\n",
    "![basicRB](figures/basicRB.png)\n",
    "\n",
    "如上图所示，$C_{i}$ 代表第 $i\\ (i = 1, 2, 3, \\dots, m)$ 个随机选取的 Clifford 门。理想情况下，即没有任何噪声的影响，假设量子比特初态为 $|\\psi\\rangle$，那么经过该随机基准测试 \\[2\\] 序列操作后量子比特的末态一定与初态相等，即以 100% 的概率仍然维持为态 $|\\psi\\rangle$，我们以末态和初态相同的概率作为随机基准测试序列保真度的度量。然而在现实中，该序列保真度会因为随着序列长度增加所积累的噪声的增加而指数式衰减。如果假设噪声与门和时间无关，即噪声的分布不随门和时间的变化而变化，则可以通过下式对该衰减曲线进行拟合：\n",
    "\n",
    "$$\n",
    "\\mathcal{F}^{(0)}=Ap_{\\rm basic}^m+B,\n",
    "$$\n",
    "\n",
    "其中 $m$ 是所施加的 Clifford 门数量。关于随机基准测试更细节的基础知识及相关理论，读者可以参阅 \\[3\\]。\n",
    "\n",
    "如上文所述，随机基准测试的一个优点是其能够排除制备和测量的错误，即将这种错误包含进上式中的参数 $A$  和 $B$ 中而不会影响曲线衰减参数 $p$。更具体地，如果将初始时刻的密度算符 $\\rho$ 和测量算符 $\\hat{E}$ 以泡利算符 $\\hat{P}_i$ 表示：\n",
    "\n",
    "$$\n",
    "\\rho=\\sum_jx_j\\hat{P}_i/d,\n",
    "$$\n",
    "\n",
    "$$\n",
    "\\hat{E}=\\sum_j\\tilde{e}_j\\hat{P}_j,\n",
    "$$\n",
    "\n",
    "那么参数 $A = \\sum_{j\\neq 0}\\tilde{e}_jx_j$, $B = \\tilde{e}_0$，其中 $d\\equiv{2^n}$，$n$ 是量子比特数目。当我们成功地对曲线进行拟合并得到参数 $p_{basic}$，便能够进一步通过下式获得该量子硬件上 Clifford 门的平均错误率 EPC(Error-rate Per Clifford)：\n",
    "\n",
    "$$\n",
    "{\\rm EPC}=\\frac{(1-p_{\\rm basic})(d-1)}{d}.\n",
    "$$\n",
    "\n",
    "\n",
    "**交插式随机基准测试**\n",
    "\n",
    "交插式随机基准测试用于基准测试某一特定量子门的平均错误率。当我们成功实现上述基本随机基准测试得到序列保真度衰减曲线后，可以将其作为参考曲线，并与交插式随机基准测试得到的衰减曲线进行对比得到某一个具体量子门的平均错误率。我们随机地选取一系列 Clifford 门，并将想要基准测试的目标门插入每一个 Clifford 门之后，然后设计最后一个门使得理想整体操作同样地为形如单位矩阵的酉变换。下图所示的交插式随机基准测试序列以 Hadamard 门（H 门）作为目标测试门：\n",
    "\n",
    "![interleavedRB](figures/interleavedRB.png)\n",
    "\n",
    "并使用下式对序列保真度衰减曲线进行拟合：\n",
    "\n",
    "$$\n",
    "\\mathcal{F}^{(0)\\prime}=A^{\\prime}p_{\\rm gate}^m+B^{\\prime}.\n",
    "$$\n",
    "\n",
    "最后，通过与基本随机基准测试所得曲线进行比较计算获得平均门错误率 EPG(Error-rate Per Gate):\n",
    "\n",
    "$$\n",
    "r_{\\rm gate}=\\frac{(1-p_{\\rm gate}/p_{\\rm ref})(d-1)}{d}.\n",
    "$$\n",
    "\n",
    "这个从真实实验数据中获取的平均错误率 $r$ 能够用来表征量子门的表现好坏。 \n",
    "\n",
    "下面将介绍如何使用量脉对量子硬件中某一个量子比特进行随机基准测试。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fcbea390",
   "metadata": {},
   "source": [
    "## 准备工作\n",
    "\n",
    "首先我们需要调用必要的包，并通过输入 token 接入云端服务:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d82829f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import the necessary packages\n",
    "from Quanlse.Utils.RandomizedBenchmarking import RB\n",
    "from Quanlse.Utils.Functions import basis, tensor\n",
    "from Quanlse.QOperation import FixedGate\n",
    "from Quanlse.Superconduct.Simulator import PulseModel\n",
    "from Quanlse.Superconduct.SchedulerSupport import SchedulerSuperconduct\n",
    "from Quanlse.Superconduct.SchedulerSupport.GeneratorRBPulse import SingleQubitCliffordPulseGenerator\n",
    "from Quanlse import Define\n",
    "\n",
    "from math import pi\n",
    "from scipy.optimize import curve_fit\n",
    "from matplotlib import pyplot as plt\n",
    "\n",
    "# Import Define class and set the token\n",
    "# Please visit http://quantum-hub.baidu.com\n",
    "from Quanlse import Define\n",
    "Define.hubToken = ''"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "383ba577",
   "metadata": {},
   "source": [
    "## 定义虚拟量子硬件模拟器"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ce848df3",
   "metadata": {},
   "source": [
    "为了完成随机基准测试，需要定义一个含噪的虚拟量子硬件作为我们的硬件平台，并选择需要基准测试的量子比特和目标门。\n",
    "\n",
    "量脉支持用户自定义多比特含噪模拟器，更多细节可参照[多比特含噪模拟器](https://quanlse.baidu.com/#/doc/tutorial-multi-qubit-noisy-simulator)。这里，我们使用量脉定义一个两比特含噪量子虚拟硬件，每一个量子比特都是三能级人造原子系统，并表征 H 门作用在第一个量子比特上的表现："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fa667d7e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define the basic parameters of the simulator\n",
    "sysLevel = 3  # The number of energy levels of each qubit\n",
    "qubitNum = 2  # The number of qubits simulator has\n",
    "\n",
    "# Qubit frequency & anharmonicity\n",
    "wq0 = 5.033 * (2 * pi)  # The frequency for qubit 0, in 2 pi GHz\n",
    "wq1 = 5.292 * (2 * pi)  # The frequency for qubit 1, in 2 pi GHz\n",
    "anharm0 = - 0.37612 * (2 * pi)  # The anharmonicity for qubit 0, in 2 pi GHz\n",
    "anharm1 = - 0.32974 * (2 * pi)  # The anharmonicity for qubit 1, in 2 pi GHz\n",
    "qubitFreq = {0: wq0, 1: wq1}\n",
    "qubitAnharm = {0: anharm0, 1: anharm1}\n",
    "\n",
    "# Coupling map between qubits\n",
    "g01 = 0.002 * (2 * pi)\n",
    "couplingMap = {(0, 1): g01}\n",
    "\n",
    "# Taking T1 & T2 dissipation into consideration, in the unit of nanosecond\n",
    "t1List = {0: 70270, 1: 59560}\n",
    "t2List = {0: 43150, 1: 23790}\n",
    "\n",
    "# Sampling time\n",
    "dt = 1.  \n",
    "\n",
    "# Build a virtual QPU\n",
    "model = PulseModel(subSysNum=qubitNum,\n",
    "                   sysLevel=sysLevel,\n",
    "                   couplingMap=couplingMap,\n",
    "                   qubitFreq=qubitFreq,\n",
    "                   dt=dt,\n",
    "                   qubitAnharm=qubitAnharm,\n",
    "                   T1=t1List, T2=t2List,\n",
    "                   ampSigma=0.0001)\n",
    "ham = model.createQHamiltonian()\n",
    "\n",
    "# The initial state of this simulator\n",
    "initialState = tensor(basis(3, 0), basis(3, 0))\n",
    "\n",
    "# Decide the qubit we want to benchmark\n",
    "targetQubitNum = 0\n",
    "hamTarget = ham.subSystem(targetQubitNum)\n",
    "\n",
    "# Decide one specific gate we want to benchmark\n",
    "targetGate = FixedGate.H"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a349539",
   "metadata": {},
   "source": [
    "上述定义完成后，便做好了进行随机基准测试的准备。\n",
    "\n",
    "由于后续会涉及到大量脉冲序列，我们需要实例化一个量脉超导调度器 `SchedulerSuperconduct()` 用来对脉冲进行自定义排布："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7d608411",
   "metadata": {},
   "outputs": [],
   "source": [
    "sche = SchedulerSuperconduct(dt=dt, ham=hamTarget, generator=SingleQubitCliffordPulseGenerator(hamTarget))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "20f344c8",
   "metadata": {},
   "source": [
    "## 实施随机基准测试"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "00d80a50",
   "metadata": {},
   "source": [
    "调用 `RB` 模块，需要传入一些必要的参数进行随机基准测试，输入参数包括：我们所定义的量子硬件 `model` 与该硬件上量子比特的初态 `initialState`；所需要基准测试的量子比特索引 `targetQubitNum`；不同 Clifford 门个数列表 `size`；每一个 Clifford 门个数 $m$ 所随机生成的相同长度的序列个数 `width`；所使用的调度器 `sche` 和采样率 `dt`。如果需要使用交插式随机基准测试，则需要另外地输入 `interleaved=True` 以及基准测试目标门 `targetGate`；如果需要模拟开放系统的演化，则还需要设置 `isOpen=True`："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "47bccc9d",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "# Create a list to store the outcome\n",
    "sizeSequenceFidelityBasic = []\n",
    "sizeSequenceFidelityInterleaved = []\n",
    "\n",
    "# Core parameters of an RB experiment\n",
    "size = [1, 10, 20, 50, 75, 100, 125, 150, 175, 200]\n",
    "width = 5\n",
    "\n",
    "# Start RB experiment. First get a basicRB curve used for reference. Then implement the interleavedRB to benchmark our Hadamard gate\n",
    "for i in size:\n",
    "    widthSequenceFidelityBasic = RB(model=model, targetQubitNum=targetQubitNum, initialState=initialState, size=i, width=width, sche=sche,\n",
    "                                    dt=dt, interleaved=False, isOpen=False)\n",
    "    sizeSequenceFidelityBasic.append(widthSequenceFidelityBasic)\n",
    "print(sizeSequenceFidelityBasic)\n",
    "    \n",
    "for j in size:\n",
    "    widthSequenceFidelityInterleaved = RB(model=model, targetQubitNum=targetQubitNum, initialState=initialState, size=j, width=width,\n",
    "                                          targetGate=targetGate, sche=sche, dt=dt, interleaved=True, isOpen=False)\n",
    "    sizeSequenceFidelityInterleaved.append(widthSequenceFidelityInterleaved)\n",
    "print(sizeSequenceFidelityInterleaved)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db1668e7",
   "metadata": {},
   "source": [
    "当我们成功运行上述两种随机基准测试方法并获得大量实验数据绘制成衰减曲线后，便能够通过下面曲线拟合的方法获得 EPC 及 EPG："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "02a4a7be",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define the fitting function\n",
    "def fit(x, a, p, b):\n",
    "    \"\"\"\n",
    "    Define the fitting curve\n",
    "    \"\"\"\n",
    "    return a * (p ** x) + b\n",
    "\n",
    "# Define the function of calculating the EPG(Error-rate Per Gate) with p_{gate} and p_{ref}\n",
    "def targetGateErrorRate(pGate, pRef, dimension):\n",
    "    \"\"\"\n",
    "    Calculate the specific gate error rate\n",
    "    \"\"\"\n",
    "    return ((1 - (pGate / pRef)) * (dimension - 1)) / dimension\n",
    "\n",
    "\n",
    "# Get the EPC(Error-rate Per Clifford) and p_{ref}\n",
    "fitparaBasic, fitcovBasic = curve_fit(fit, size, sizeSequenceFidelityBasic, p0=[0.5, 1, 0.5], maxfev=500000,\n",
    "                                      bounds=[0, 1])\n",
    "pfitBasic = fitparaBasic[1]\n",
    "rClifford = (1 - pfitBasic) / 2\n",
    "print('EPC =', rClifford)\n",
    "\n",
    "# Get the parameter p_{gate}\n",
    "fitparaInterleaved, fitcovInterleaved = curve_fit(fit, size, sizeSequenceFidelityInterleaved,\n",
    "                                                  p0=[fitparaBasic[0], 1, fitparaBasic[2]], maxfev=500000,\n",
    "                                                  bounds=[0, 1])\n",
    "pfitInterleaved = fitparaInterleaved[1]\n",
    "yfitBasic = fitparaBasic[0] * (pfitBasic ** size) + fitparaBasic[2]\n",
    "yfitInterleaved = fitparaInterleaved[0] * (pfitInterleaved ** size) + fitparaInterleaved[2]\n",
    "EPG = targetGateErrorRate(pfitInterleaved, pfitBasic, dimension=2)\n",
    "print('EPG =', EPG)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "459e9f78",
   "metadata": {},
   "source": [
    "并同时绘制实验数据及拟合曲线来可视化该衰减现象:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8279d3fa",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Plot the decay curve of our RB experiment\n",
    "plt.figure(figsize=(18, 6), dpi=80)\n",
    "plt.figure(1)\n",
    "ax1 = plt.subplot(121)\n",
    "ax1.plot(size, sizeSequenceFidelityBasic, '.b', label='experiment simulation data')\n",
    "ax1.plot(size, yfitBasic, 'r', label='fitting curve')\n",
    "plt.xlabel('$m$')\n",
    "plt.ylabel('Sequence Fidelity')\n",
    "plt.title('basic RB using Quanlse')\n",
    "plt.legend()\n",
    "ax2 = plt.subplot(122)\n",
    "ax2.plot(size, sizeSequenceFidelityInterleaved, '.b', label='experiment simulation data')\n",
    "ax2.plot(size, yfitInterleaved, 'r', label='fitting curve')\n",
    "plt.xlabel('$m$')\n",
    "plt.ylabel('Sequence Fidelity')\n",
    "plt.title('interleaved RB using Quanlse')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e61bd138",
   "metadata": {},
   "source": [
    "其中，$m$ 代表序列中 Clifford 门的个数。可以看出，通过本方案，我们可以自动生成适配目标量子硬件的门操作的高精度脉冲，在脉冲数量显著增加时对其进行脉冲调度，并进一步对量子硬件进行随机基准测试实验来获得上图所示的衰减曲线，曲线反映了随着门的数量（脉冲数）增加而累积的噪声导致序列保真度指数衰减这一现象。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7d9047f",
   "metadata": {},
   "source": [
    "## 总结\n",
    "\n",
    "本教程描述了如何使用量脉对量子硬件进行随机基准测试来表征某一个门的平均错误率。用户可以通过链接 [tutorial-randomized-benchmarking.ipynb](https://github.com/baidu/Quanlse/blob/main/Tutorial/CN/tutorial-randomized-benchmarking-cn.ipynb) 跳转到相应的 GitHub 页面获取相关代码。我们推荐用户使用不同于本教程的参数来获得更好的曲线拟合效果，并开发更为前沿的随机基准测试变种方法。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "214a647a",
   "metadata": {},
   "source": [
    "## 参考文献\n",
    "\\[1\\] [Kelly, Julian, et al. \"Optimal quantum control using randomized benchmarking.\" *Physical review letters* 112.24 (2014): 240504.](https://doi.org/10.1103/PhysRevLett.112.240504)\n",
    "\n",
    "\\[2\\] [Magesan, Easwar, et al. \"Efficient measurement of quantum gate error by interleaved randomized benchmarking.\" *Physical review letters* 109.8 (2012): 080505.](https://doi.org/10.1103/PhysRevLett.109.080505)\n",
    "\n",
    "\\[3\\] [Magesan, Easwar, Jay M. Gambetta, and Joseph Emerson. \"Scalable and robust randomized benchmarking of quantum processes.\" *Physical review letters* 106.18 (2011): 180504.](https://doi.org/10.1103/PhysRevLett.106.180504)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
